/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
 */

package com.ewerp.mud.storage;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.ewerp.mud.core.exceptions.EwerpMudException;
import com.ewerp.mud.core.lifecycle.ILifecycleListener;
import com.ewerp.mud.core.plugin.IPlugin;
import com.ewerp.mud.entities.IEntity;

public class EwerpPersistenceManager implements IPlugin, IPersistenceManager, ILifecycleListener {
	private static EwerpPersistenceManager instance = new EwerpPersistenceManager();

	private static final SessionFactory sessionFactory = buildSessionFactory();

	private static SessionFactory buildSessionFactory() {
		try {
			// Create the SessionFactory from hibernate.cfg.xml
			return new Configuration().configure().buildSessionFactory();
		} catch (Throwable ex) {
			// Make sure you log the exception, as it might be swallowed
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}
	
	@Override
	public Class<?>[] getInterfaces() {
		return new Class<?>[] { IPersistenceManager.class };
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	
	public static EwerpPersistenceManager getInstance() {
		if(instance == null) {
            instance = new EwerpPersistenceManager();
        }
        return instance;
	}
	
	private EwerpPersistenceManager() {
	}

	@Override
	public void init() {
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void start() {
		// TODO Auto-generated method stub

	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub

	}

	@Override
	public Object fetchObject(Class<?> clazz) throws EwerpMudException {
		List<Object> result = fetchObjects(clazz);
		
		if(result != null && result.size() <= 0) {
			return null;
		} else if(result.size() != 1) {
			throw new EwerpMudException("Too many results");
		}
		
		return result.get(0);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Object> fetchObjects(Class<?> clazz) {
		Session session = EwerpPersistenceManager.getSessionFactory().getCurrentSession();
		
		List<?> result = session.createQuery("from " + clazz.getName()).list();
		
		for(int i = 0; i < result.size(); i++) {
			System.out.println(result.get(i));
		}

		return (List<Object>)result;
	}
	
	public void saveObject(IEntity entity) {
		Session session = EwerpPersistenceManager.getSessionFactory().getCurrentSession();
		
		// If this has not been initialized within hibernate yet, then save it
		if(entity.getSerial() == 0) {
			session.save(entity);
		} else {
			session.saveOrUpdate(entity);
		}
	}
	
	public void beginTransaction() {
		Session session = EwerpPersistenceManager.getSessionFactory().getCurrentSession();
		session.beginTransaction();
	}
	
	public void commitTransaction() {
		Session session = EwerpPersistenceManager.getSessionFactory().getCurrentSession();
		session.getTransaction().commit();
	}
	
	public void rollbackTransaction() {
		Session session = EwerpPersistenceManager.getSessionFactory().getCurrentSession();
		session.getTransaction().rollback();
	}
	
	public void closeSession() {
		EwerpPersistenceManager.getSessionFactory().getCurrentSession().close();
	}

}
